﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Web.Mvc;
using EGym.BL.DataGestor;
using EGym.BL.Exceptions;
using EGym.BL.Forms;
using EGym.Data;

namespace EGym.BL
{
    public class AfiliadoGestor : BaseGestor
    {

        #region Constantes
        private const string ESTADO_SAO_PAULO = "São Paulo";
        private const string PESSOA_JURIDICA = "Juridica";
        private const string PESSOA_FISICA = "Fisica";
        #endregion

        #region Propriedades
        public IEnumerable<BussinessLayerEntryException> BussinessLayerEntryExceptions { get; private set; }
        #endregion

        #region Construtores
        public AfiliadoGestor(DBDataContext db)
        {
            BussinessLayerEntryExceptions = new List<BussinessLayerEntryException>();
            DB = db;
        }
        #endregion


        #region Metodos

        #region Publicos

        #region Métodos para retorno de Formulários
        public AfiliadoForm GetFormForInsert()
        {
            AfiliadoForm form = new AfiliadoForm();
            
            form.Afiliado = new Afiliado();
            form.Afiliado.AfiliadoJuridico = new AfiliadoJuridico();
            form.Afiliado.AfiliadoFisico = new AfiliadoFisico();

            FillListaTipoDeEndereco(form);

            return form;
        }
        
        public AfiliadoForm GetFormForEdit(int id)
        {
            AfiliadoForm form = new AfiliadoForm();
            form.Afiliado = GetAfiliadoById(id);
            AfiliadoEndereco afiliadoEndereco = form.Afiliado.AfiliadoEnderecos.FirstOrDefault();
            form.EnderecoDoAfiliado = afiliadoEndereco  != null ? afiliadoEndereco.Endereco : new Endereco();



            form.TipoDePessoaSelecionada = form.Afiliado.AfiliadoJuridico != null ? PESSOA_JURIDICA : PESSOA_FISICA;
            if (afiliadoEndereco != null)
            {
                form.TipoDeEnderecoSelecionada = form.EnderecoDoAfiliado.EnderecoTipo.Nome;
                form.EstadoSelecionado = form.EnderecoDoAfiliado.Estado.Nome;
            }
            else
            {
                EnderecoGestor enderecoGestor = new EnderecoGestor(DB);
                form.EnderecoDoAfiliado.Estado = enderecoGestor.GetEstadoByNome(ESTADO_SAO_PAULO);
                
            }
            FillAssociacaoEnderecoData(form);

            return form;
        }

        #endregion


        /// <summary>
        /// Retorna uma lista com todos afiliados cadastrados.
        /// </summary>
        /// <returns>Lista de <c ref="EGym.Data.Afiliado">Afiliado</c></returns>
        public IEnumerable<Afiliado> GetAfiliados()
        {
            var list = (from reg in DB.Afiliados
                        select reg
                        );
            return list;
        }

        public Afiliado GetAfiliadoById(int id)
        {
            var afiliado = (from reg in DB.Afiliados
                            where reg.AfiliadoId.Equals(id) 
                            select reg
                            ).FirstOrDefault();
            return afiliado;
        }

        public bool CpfJaCadastrado(string cpf)
        {
            var afiliadoFisico = (from reg in DB.AfiliadoFisicos
                           where reg.CPF.ToLower().Equals(cpf.ToLower()) 
                           select reg
                           ).FirstOrDefault();
            return afiliadoFisico != null;
        }
        public bool RgJaCadastrado(string rg)
        {
            var afiliadoFisico = (from reg in DB.AfiliadoFisicos
                           where reg.RG.ToLower().Equals(rg.ToLower()) 
                           select reg
                           ).FirstOrDefault();
            return afiliadoFisico != null;
        }
        
        public bool CnpjJaCadastrado(string cnpj)
        {
            var afiliadoJuridico = (from reg in DB.AfiliadoJuridicos
                                  where reg.CNPJ.ToLower().Equals(cnpj.ToLower())
                                  select reg
                           ).FirstOrDefault();
            return afiliadoJuridico != null;
        }

        public bool IeJaCadastrado(string ie)
        {
            var afiliadoJuridico = (from reg in DB.AfiliadoJuridicos
                                    where reg.IE.ToLower().Equals(ie.ToLower())
                                    select reg
                           ).FirstOrDefault();
            return afiliadoJuridico != null;
        }

        public void EfeutaInscricao(AfiliadoForm form)
        {
            form.BussinessLayerEntryExceptions= ValidaInscricao(form);

            if (form.DadosSaoValidos())
            {
                
                if (form.TipoDePessoaSelecionada.Equals(PESSOA_JURIDICA))
                    form.Afiliado.AfiliadoFisico = null;
                // DB.AfiliadoJuridicos.InsertOnSubmit(form.Afiliado.AfiliadoJuridico);
                if (form.TipoDePessoaSelecionada.Equals(PESSOA_FISICA))
                    form.Afiliado.AfiliadoJuridico = null;
                //DB.AfiliadoFisicos.InsertOnSubmit(form.Afiliado.AfiliadoFisico);
                //Aplica campos Automáticos
                AplicaValoresAutomaticosParaInsercao(form.Afiliado);
                DB.Afiliados.InsertOnSubmit(form.Afiliado);
                //Inscreve usuario como afiado;
                UsuarioGestor usuarioGestor = new UsuarioGestor(DB);
                usuarioGestor.EfeutaInscricaoUsuarioAdministradorAfiliacao(form);
                //Propaga as alterações no Banco de dados.
                DB.SubmitChanges(ConflictMode.FailOnFirstConflict);

                usuarioGestor.EnviaEmailAoUsuarioSobreInscricao(form);
            }

        }
        #endregion

        #region Privados

        public void FillAssociacaoEnderecoData(AfiliadoForm form)
        {
            if (form.Afiliado.AfiliadoId > 0)
            {
                var enderecoDoAfiliado = (from reg in DB.AfiliadoEnderecos
                                          where reg.AfiliadoId.Equals(form.Afiliado.AfiliadoId)
                                          select reg).FirstOrDefault();

                if (enderecoDoAfiliado != null)
                    form.EnderecoDoAfiliado = enderecoDoAfiliado.Endereco;

                FillListaTipoDeEndereco(form);

                FillListaEstado(form);
            }
        }

        private void FillListaTipoDeEndereco(AfiliadoForm form)
        {
            List<string> tipoDeEnderecoLista = new List<string>();

            foreach(var item in DB.EnderecoTipos)
                tipoDeEnderecoLista.Add(item.Nome );

            form.TipoDeEndereco = new SelectList(tipoDeEnderecoLista, form.EnderecoDoAfiliado.EnderecoTipoId);
        }
        private void FillListaEstado(AfiliadoForm form)
        {
            List<string> estados = new List<string>();

            foreach (var item in DB.Estados)
                estados.Add(item.Nome);

            form.Estado = new SelectList(estados, form.EnderecoDoAfiliado.Estado != null ?  "São Paulo" : form.EnderecoDoAfiliado.Estado.Nome );
        }

        private void AplicaValoresAutomaticosParaInsercao(Afiliado afiliado)
        {
            afiliado.DataCadastro = DateTime.Now;
            afiliado.AfiliadoId = NextId();
        }

        private int NextId()
        {
            var afiliado = (from reg in DB.Afiliados
                            orderby reg.AfiliadoId descending
                          select reg).FirstOrDefault();
            int retorno = afiliado != null ? afiliado.AfiliadoId + 1 : 1;
            return retorno;
        }

        private IEnumerable<BussinessLayerEntryException>  ValidaInscricao(AfiliadoForm form)
        {
            return ValidaExistencia(form);
        }

        private IEnumerable<BussinessLayerEntryException>  ValidaExistencia(AfiliadoForm form)
        {
            var bussinessLayerEntryExceptions = new List<BussinessLayerEntryException>();

            bussinessLayerEntryExceptions.AddRange(ValidaExistenciaPessoaFisica(form));

            bussinessLayerEntryExceptions.AddRange(ValidaExistenciaPessoaJuridica(form));

            return bussinessLayerEntryExceptions;
        }

        private IEnumerable<BussinessLayerEntryException> ValidaExistenciaPessoaFisica(AfiliadoForm form)
        {
            var bussinessLayerEntryExceptions = new List<BussinessLayerEntryException>();

            if (form.TipoDePessoaSelecionada.Equals(PESSOA_FISICA))
            {
                AfiliadoFisico afiliadoFisico =
                    DB.AfiliadoFisicos.FirstOrDefault(o => o.CPF.Equals(form.Afiliado.AfiliadoFisico.CPF));

                if (afiliadoFisico!= null)
                    bussinessLayerEntryExceptions.Add(new BussinessLayerEntryException("ExistenciaPessoaFisica",
                                                 "O Afiliado já encontra-se cadastrado no banco de dados",
                                                 BussinessLayerEntryExceptionTypes.ItemInformadoExistenteNoBancoDados,
                                                 form.Afiliado.AfiliadoFisico,
                                                 afiliadoFisico));
                    
            }
            return bussinessLayerEntryExceptions;
        }

        private IEnumerable<BussinessLayerEntryException>  ValidaExistenciaPessoaJuridica(AfiliadoForm form)
        {
            var bussinessLayerEntryExceptions = new List<BussinessLayerEntryException>();

            if (form.TipoDePessoaSelecionada.Equals(PESSOA_JURIDICA))
            {
                AfiliadoJuridico afiliadoJuridico =
                    DB.AfiliadoJuridicos.FirstOrDefault(o => o.CNPJ.Equals(form.Afiliado.AfiliadoJuridico.CNPJ));

                if (afiliadoJuridico != null)
                    bussinessLayerEntryExceptions.Add(new BussinessLayerEntryException("ExistenciaPessoaJuridica",
                                                 "O Afiliado já encontra-se cadastrado no banco de dados",
                                                 BussinessLayerEntryExceptionTypes.ItemInformadoExistenteNoBancoDados,
                                                 form.Afiliado.AfiliadoJuridico,
                                                 afiliadoJuridico));

            }
            return bussinessLayerEntryExceptions;

        }


        #endregion
        #endregion
    }
}
